#include "LPC17xx.h"
#include "adc.h"
#include "pin_config.h"
#include "gpio.h"
#include "interrupt.h"
#include "uart.h"

/* global buffer for adc values */
volatile uint32_t adc_value[ADC_COUNT];

/**
 * ADC interrupt service routine
 *
 * @param  none
 * @return none
 *
 * @brief  Handle interrupts of finished ADC conversions
 *
 */
void adc_irq(void)
{
	uint32_t status;

	/* read interrupt status register */
	status = ADC->ADSTAT;

	/* get interrupt source */
	switch (status & 0xFF)
	{

	/* channel 0 finished conversion */
	case ADC_CHANNEL_0:
		/* read converted value, with reading this value interrupts are enabled */
		adc_value[0] = (ADC->ADDR0 >> 4) & 0x0FFF;
		break;
	default:
		break;
	}
}

/**
 * ADC initialization
 *
 * @param  none
 * @return none
 *
 * @brief  Initialize and start ADC conversion
 *
 */
void adc_init(void)
{

	/* Enable CLOCK into ADC controller */
	SC->PCONP |= ADC_POWERON;

	/* configure pin for ADC 0 */
	pin_configure(BANK_0, PIN_23, PIN_FUNCTION_1, PIN_MODE_FLOAT);

#ifdef ADC_ISR
	/* set channel 0, prescaler and switch on adc conversion */
	ADC->ADCR = ADC_CHANNEL_0 | ADC_PRESCALER | ADC_OPERATIONAL | ADC_BURST;

	/* enable interrupt for channel 0 */
	ADC->ADINTEN = ADC_INTEN0;

	/* set interrupt priority for ADC */
	NVIC_SetPriority(ADC_IRQn, ADC_NVIC_PRIO);

	/* enable interrupt in NVIC */
	NVIC_EnableIRQ(ADC_IRQn);
#endif

}

/**
 * Get ADC value
 *
 * @param  none
 * @return none
 *
 * @brief  Get adc value of converted channel
 *
 */
uint32_t adc_get(void)
{
	/* set channel 0, prescaler and switch on adc conversion */
	ADC->ADCR = ADC_CHANNEL_0 | ADC_PRESCALER | ADC_OPERATIONAL | ADC_START_CONVERSION;

	while (!(ADC->ADDR0 & ADC_DONE))
	{
		;
	}
	return ((ADC->ADDR0 & ADC_MASK) >> 6);
}
